//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//	roamtask.c
//		Roaming module
//	history :
//
//	Description:
//		The responsibility of Roaming module is to (1)check the exact connection state
//		of H/W periodically (2)in ESS, supply a candidate to handover and notify SME
//		module to join with it if the connection is lost (3)in ESS, notify SME module
//		to scan if there is not any candidate (4) notify SME module to cease the Roaming
//		task if the handover alway fails during a interval of time
//
//	Import msg:	ROAMMSG_ROAM_REQ	(from SME)
//				ROAMMSG_DEAUTHEN_IND(from SME)
//	Export msg:	SMEMSG_HANDOVER_JOIN_REQ
//				SMEMSG_SCAN_REQ
//				SMEMSG_END_ROAMING
//				SCANMSG_STOP_SCAN
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
#include "sysdef.h"

//=================== Subroutine of ROAM Module
void TryToHandover(PWB32_ADAPTER Adapter);
void vRoamTimerStart(PWB32_ADAPTER Adapter, int timeout_value);
void vRoamTimerHandler_1a(  void* Data );
void vRoamTimerHandler(	void*			SystemSpecific1,
								  PWB32_ADAPTER 	Adapter,
								 	void*			SystemSpecific2,
								 	void*			SystemSpecific3);

//=================== Action Function of ROAM Module
void vRoamProc_RoamReq(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg);
void vRoamProc_ActiveTimeout(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg);
void vRoamProc_DoubleChkLockTimeout(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg);
void vRoamProc_QueryEssTimeout(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg);
void vRoamProc_RcvDeAuthInd(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg);

//========== Define the state machine table of ROAM module =================
static K_TRANS asInActive[] =
{
	{ROAMMSG_ROAM_REQ,			vRoamProc_RoamReq			},
	{K_NULL_MSG,				vProc_Null						}
};

static const K_TRANS asActive[] =
{
	{ROAMMSG_DEAUTHEN_IND,		vRoamProc_RcvDeAuthInd			},
	{ROAMMSG_TIMEOUT,			vRoamProc_ActiveTimeout	},
	{K_NULL_MSG,				vProc_Null						}
};

static const K_TRANS asDoubleCheckLock[] =
{
	{ROAMMSG_DEAUTHEN_IND,		vRoamProc_RcvDeAuthInd	},
	{ROAMMSG_TIMEOUT,			vRoamProc_DoubleChkLockTimeout	},
	{K_NULL_MSG,				vProc_Null						}
};

static const K_TRANS asQueryEss[] =
{
	{ROAMMSG_ROAM_REQ,			vRoamProc_RoamReq			},
	{ROAMMSG_TIMEOUT,			vRoamProc_QueryEssTimeout		},
	{K_NULL_MSG,				vProc_Null						}
};

//========= ROAM State Transition Table ==============================
static const K_TRANS* psRoamTransTable[] =
{
	asInActive,
	asActive,
	asDoubleCheckLock,
	asQueryEss
};

//=========================================================================
//      Subroutine of ROAM Module
//=========================================================================
unsigned char boRoam_InactiveState(PWB32_ADAPTER Adapter)
{
	return (psROAM->wState==ROAM_INACTIVE);
}

void Roam_Init(PWB32_ADAPTER Adapter)
{
	Roam_ResetPara(Adapter);
	///NdisMInitializeTimer(&(psROAM->nTimer),
    ///                      Adapter->WbNdis.MiniportAdapterHandle,
    ///                      (void*) vRoamTimerHandler,
    ///                      (void*) Adapter);
	OS_TIMER_INITIAL( 	&(psROAM->nTimer),
                          (void*) vRoamTimerHandler,
                          (void*) Adapter);
}

void Roam_ResetPara(PWB32_ADAPTER Adapter)
{
	psROAM->wState = ROAM_INACTIVE;
	psROAM->wUnlockNum = 0;
	psROAM->wSignalLostNum = 0;
	psROAM->TimeCount = 1;
	Adapter->Mds.TxToggle = FALSE;
	psROAM->TimeToIndDisc = TIMECOUNT_TO_INDICATE_DISCONNECT;
}

void Roam_Halt(PWB32_ADAPTER Adapter)
{
	vRoamTimerStop(Adapter);
	while (psROAM->boInTimerHandler == TRUE)
	{
		///NdisMSleep(10000);//10ms
		OS_SLEEP( 10000 ); //10ms
	}
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("STATE: Roam halt.\n"));
	#endif

}

void Roam_Stop(PWB32_ADAPTER Adapter)
{
	vRoamTimerStop(Adapter);
}

void Roam_Entry(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg)
{

	if (psRoamMsg->wMsgType==KNLMSG_RESET)
	{	// stop Roam Timer and Roam State
		psROAM->wState=ROAM_INACTIVE;
		vRoamTimerStop(Adapter);
		return;
	}
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("STATE: iROAM s=%x, m=%x, t=%x, rssi=%x\n", psROAM->wState, psRoamMsg->wMsgType,
					psROAM->wUnlockNum, psROAM->wSignalLostNum));
	#endif
	vKNL_StateMachine(Adapter, psRoamTransTable, 
						psROAM->wState, psRoamMsg);
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("STATE: oROAM s=%x\n", psROAM->wState));
	#endif
}

void TryToHandover(PWB32_ADAPTER Adapter)
{
	K_MSG	sMsg;
	u16	i;

	/*The state of the AP that just lost the connection will not be changed. Because it has
	a chance to come back to CONNECTED state. ???
	*/
	//if (psBSS(psSME->wDesiredJoinBSS)->bBssType == ESS_NET)
	//If the "previous connection" is ESS_NET, it is just necessary to handover.
	/*After connection, the psLOCAL->wConnectedSTAindex is not zero when enter this
	  function first time. If enter this function more than once, the
	  psLOCAL->wConnectedSTAindex still will not be zero in IBSS mode. Because it won't
	  try to handover. The psLOCAL->wConnectedSTAindex will be zero only when the bss
	  type is ESS_NET and try to handover fail at least once.*/
/*	if (((psLOCAL->wConnectedSTAindex != 0) && 
		(psBSS(psLOCAL->wConnectedSTAindex)->bBssType == ESS_NET))||
		(psLOCAL->wConnectedSTAindex == 0))
*/
	//IBSS mode will not roam. Just use this module to detect if this IBSS is dismissed
	//(only local STA exist)
	if ((psLOCAL->wConnectedSTAindex != 0) &&
		(psBSS(psLOCAL->wConnectedSTAindex)->bBssType == IBSS_NET))
		return;

	else
	{
#if 0
		//[WKCHEN]  Won't do the roaming here, let the NDIS take this.
		//			But will rejoin again to avoid the effect of busy traffic in the air
		//			If the authentication mode is WPAPSK or WPA, should not rejoin.
		//			Because if turning the AP off and then on immediately, Key will be
		//			different.
		//i = wRoamingQuery(Adapter);
		//if ((psSME->bDesiredAuthMode != WPA_AUTH) &&
		//	(psSME->bDesiredAuthMode != WPAPSK_AUTH))
		//{
		//	i = psLOCAL->wConnectedSTAindex;
		//}
		//else
			i = 0;

		if (i)	//Reconnect with it
		{
			if (psROAM->wState == QUERY_ESS)
			{
				sMsg.wMsgType = SCANMSG_STOP_SCAN;
				sMsg.pMsgPtr = NULL;
				Scan_Entry(Adapter, &sMsg);
			}
			//((PMACADDR)psSME->abDesiredBSSID)->ll = ((PMACADDR)psBSS(i)->abBssID)->ll;
			//((PMACADDR)psSME->abDesiredBSSID)->ss = ((PMACADDR)psBSS(i)->abBssID)->ss;
			//only use BSSID
			//if (psSME->boDUTmode == TRUE) // DUTmode,join only set BSSID

			//20040229
			//psSME->sDesiredSSID.Length = 0;
			#ifdef _PE_STATE_DUMP_
			WBDEBUG(("STATE: Reconnect DesirJoinIdx=%x\n",i));
			#endif

/*
			sMsg.wMsgType = SMEMSG_HANDOVER_JOIN_REQ;
			sMsg.pMsgPtr = &i;	//Desired join BSSdescription index
			SME_Entry(Adapter, &sMsg);
*/
			ClearBSSdescpt(Adapter, i);
			sMsg.wMsgType = SMEMSG_SCAN_JOIN_REQ;
			sMsg.pMsgPtr = NULL;
			SME_Entry(Adapter, &sMsg);
		}
		else	//Perform scan
		{
			#ifdef NDIS50_MINIPORT
			sMsg.wMsgType = SMEMSG_SCAN_REQ;
			sMsg.pMsgPtr = NULL;
			SME_Entry(Adapter, &sMsg);
			#endif
		}
#else
		i = wRoamingQuery(Adapter);

		if (i>1)
		{
			sMsg.wMsgType = SMEMSG_HANDOVER_JOIN_REQ;
			sMsg.pMsgPtr = &i;	//Desired join BSSdescription index
			SME_Entry(Adapter, &sMsg);
		}
#endif
	}

}

void vRoamTimerStart(PWB32_ADAPTER Adapter, int timeout_value)
{
	// NOTE: duplicate call NdisMSetTimer() will Stop old Timer and ReStart new Timer
	if (Adapter->sLocalPara.ShutDowned == FALSE)
	{
    	if (timeout_value<MIN_TIMEOUT_VAL)
			timeout_value=MIN_TIMEOUT_VAL;
		///NdisMSetTimer( &(psROAM->nTimer), timeout_value);
		OS_TIMER_SET( &(psROAM->nTimer), timeout_value);

	}
}

void vRoamTimerStop(PWB32_ADAPTER Adapter)
{

	OS_TIMER_CANCEL( &psROAM->nTimer, &boValue);
	#ifdef _PE_STATE_DUMP_
	WBDEBUG(("STATE: roam cancel timer return valule =%x\n", boValue));
	#endif
}

//for only one argument
void vRoamTimerHandler_1a( void* Data)
{
	vRoamTimerHandler(NULL, (PWB32_ADAPTER)Data, NULL, NULL);
}

void vRoamTimerHandler( void*			SystemSpecific1,
					   PWB32_ADAPTER 	Adapter,
					   void*			SystemSpecific2,
					   void*			SystemSpecific3)
{
	K_MSG sTimerMsg;
	K_MSG	sSmeMsg;
	u8		PsMode;

	//Adapter->Mds.TxToggle = FALSE; move to wbndis51.c to clear per 2 seconds [20050706]
    Wepkey_ErrCheck(Adapter);

	if (psROAM->TimeCount == ROAM_LOCK_PERIOD)
	{
		//Checking for power save
		if ((psSME->bDesiredPowerSave) &&
			(psBSS(psLOCAL->wConnectedSTAindex)->bBssType == ESS_NET))
		{
			if (psLOCAL->boMacPsValid == FALSE)
				hal_get_power_save_mode(&Adapter->sHwData, &psLOCAL->iPowerSaveMode);
			if (!psLOCAL->boHasTxActivity)
			{
				switch (psLOCAL->CheckCountForPS)
				{
					case (PWR_TX_IDLE_CYCLE - 1):
						//We get the H/W MAC power state for the preparing to enter power save state
						hal_get_power_save_mode(&Adapter->sHwData, &psLOCAL->iPowerSaveMode);
						break;
					case PWR_TX_IDLE_CYCLE:
						//We have not transmitted packets for a long time, so we try to enter
						//power save state.
						if (psLOCAL->iPowerSaveMode != PWR_SAVE)
						{
							#ifdef _PE_STATE_DUMP_
							WBDEBUG(("There is no data for tx, enter power save.\n"));
							#endif
							//There is no tx activity during the checking interval
							PsMode = PWR_SAVE;
							sSmeMsg.wMsgType = SMEMSG_POWERSAVE_REQ;
							sSmeMsg.pMsgPtr = &PsMode;
							SME_Entry(Adapter, &sSmeMsg);
						}
						psLOCAL->boMacPsValid = FALSE;	//The power save command may fail,
														//so we'll query H/W state next time.
						psLOCAL->CheckCountForPS = 0;
						break;
					default:
						break;
				}
				psLOCAL->CheckCountForPS++;
			}
			else
			{
				psLOCAL->boHasTxActivity = 0;
				psLOCAL->CheckCountForPS = 0;
			}

			//Don't check connect status temporarily to avoid disconnect
			//if (psLOCAL->iPowerSaveMode == PWR_SAVE)
			//	psLOCAL->bConnectFlag = 1;
		}

		// every (ROAM_TIME_PERIOD * ROAM_LOCK_PERIOD) will check the connect status
		psROAM->TimeCount = 1;
		psROAM->boInTimerHandler = TRUE;
    	sTimerMsg.wMsgType = ROAMMSG_TIMEOUT;
		sTimerMsg.pMsgPtr = NULL;
		Roam_Entry(Adapter, &sTimerMsg);
		psROAM->boInTimerHandler = FALSE;
	}
	else
	{
		//Every ROAM_TIME_PERIOD will check the DTO
		if (psLOCAL->TxRateMode == RATE_AUTO)
		{
			MTO_PeriodicTimerExpired(Adapter);
		}
		psROAM->TimeCount++;
		vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
	}
}

unsigned char boIsReceiveBeacon(PWB32_ADAPTER Adapter)
{
	if (psROAM->wUnlockNum >2)
		return FALSE;
	else
		return TRUE;
}

//======================================================================================
//      Action Function of ROAM State Transition Table 
//======================================================================================
void vRoamProc_RoamReq(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg)
{
	phw_data_t pHwData = &Adapter->sHwData;
	//In ROAM module, the update of psLOCAL->wOldSTAindex and wConnectedSTAindex
	//variables is forbidden
	vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
	psROAM->wUnlockNum = 0;
	psROAM->wSignalLostNum = 0;
	psROAM->wState=ACTIVE;
	if ((psSME->bDesiredPowerSave) &&
		(psBSS(psLOCAL->wConnectedSTAindex)->bBssType == ESS_NET))
	{
		//reduce the chance to indicate disconneced.
		psROAM->TimeToIndDisc = PS_TIMECOUNT_TO_INDICATE_DISCONNECT;
	}
	else
		psROAM->TimeToIndDisc = TIMECOUNT_TO_INDICATE_DISCONNECT;

	if (psLOCAL->boHandover == TRUE)
	{
		psROAM->RoamTime = hal_get_time_count( pHwData ) / 10; // 20060627.2 /10 = 1second
	}
	else
		psROAM->RoamTime = 0;	//indicate this connection is not arised by the handover
}

#if 0
void vRoamProc_ActiveTimeout(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg)
{
	if (boCheckConnect(Adapter) == TRUE)
	{
		psROAM->wUnlockNum = 0;
		vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
	}
	else
	{
		psROAM->wUnlockNum++;
		vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
		psROAM->wState = DOUBLE_CHK_LOCK;
	}
}

void vRoamProc_DoubleChkLockTimeout(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg)
{
	if (boCheckConnect(Adapter) == TRUE)
	{
		psROAM->wUnlockNum = 0;
		vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
		psROAM->wState = ACTIVE;
	}
	else
	{
		//if (psROAM->wUnlockNum >= 5)
		if ( psROAM->wUnlockNum >= (psROAM->TimeToIndDisc-4) )
		{
			K_MSG	sMsg;
			SCAN_REQ_PARA	sScanReqPara;

			//TryToHandover(Adapter);
			//prepare to roam to another AP
			sMsg.wMsgType = SMEMSG_SCAN_REQ;
			//Scan with unicast SSID. Only change SSID parameters.
			memcpy( &sScanReqPara, psSCANREQ , sizeof(SCAN_REQ_PARA) );
			memcpy( &sScanReqPara.sSSID, &psSME->sDesiredSSID, sizeof(struct SSID_Element) );
			sMsg.pMsgPtr = &sScanReqPara;
			SME_Entry(Adapter, &sMsg);

			psROAM->wState = QUERY_ESS;
		}
		psROAM->wUnlockNum++;
		vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
	}
}

void vRoamProc_QueryEssTimeout(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg)
{
	K_MSG	sMsg;
	u16	wReason;

	if (boCheckConnect(Adapter) == TRUE)
	{
		psROAM->wUnlockNum = 0;
		vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
		psROAM->wState = ACTIVE;
	}
	else
	{
		//if (psROAM->wUnlockNum < 10)	//total 10 sec.
		//if (psROAM->wUnlockNum < 7)	//total 7 sec.
		if (psROAM->wUnlockNum < psROAM->TimeToIndDisc)	//total 7 sec.
		{
			if (psROAM->wUnlockNum >= (psROAM->TimeToIndDisc-2) )
				TryToHandover(Adapter);
			psROAM->wUnlockNum++;
			vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
		}
		else
		{
			//No candidate to join
			//psROAM->wState = ROAM_INACTIVE; It will be reset at SME
			vRoamTimerStop(Adapter);

			FillEventLog(Adapter, EVENT_LOST_SIGNAL);

			//info SME module, psLOCAL->wConnectedSTAindex may still not equal to 0
			wReason = DISASS_REASON_LEFT_BSS;
			sMsg.wMsgType = SMEMSG_END_ROAMING;
			sMsg.pMsgPtr = &wReason;
			SME_Entry(Adapter, &sMsg);
		}
	}
}
#else
void vRoamProc_ActiveTimeout(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg)
{
	if (boCheckConnect(Adapter) == TRUE)
	{
		psROAM->wUnlockNum = 0;
		if (boCheckSignal(Adapter) == TRUE)
			psROAM->wSignalLostNum = 0;
		else
		{
			psROAM->wSignalLostNum++;
			psROAM->wState = DOUBLE_CHK_LOCK;
		}
	}
	else
	{
		psROAM->wUnlockNum++;
		psROAM->wState = QUERY_ESS;
	}
	vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
}

void vRoamProc_DoubleChkLockTimeout(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg)
{
	phw_data_t pHwData = &Adapter->sHwData;
	K_MSG	sMsg;

	if (boCheckConnect(Adapter) == TRUE)
	{
		psROAM->wUnlockNum = 0;
		if (boCheckSignal(Adapter) == TRUE)
		{
			psROAM->wSignalLostNum = 0;
			psROAM->wState = ACTIVE;
		}
		else
		{
			switch (psROAM->wSignalLostNum)
			{
				case 2:
				case 6:
					{
						SCAN_REQ_PARA	sScanReqPara;

						//To avoid to handover frequently
						if ((psROAM->RoamTime != 0) && 
							(( (hal_get_time_count( pHwData )/ 10) - psROAM->RoamTime) < 30) ) // 20060627.2 Modify
						{
							//Too frequent
							#ifdef _PE_STATE_DUMP_
							//WBDEBUG(("Too frequnetly handover.\n"));
							#endif
						}
						else
						{
							//TryToHandover(Adapter);
							//prepare to roam to another AP
							sMsg.wMsgType = SMEMSG_SCAN_REQ;
							//Scan with unicast SSID. Only change SSID parameters.
							memcpy( &sScanReqPara, psSCANREQ , sizeof(SCAN_REQ_PARA) );
							memcpy( &sScanReqPara.sSSID, &psSME->sDesiredSSID, sizeof(struct SSID_Element) );
							sMsg.pMsgPtr = &sScanReqPara;
							SME_Entry(Adapter, &sMsg);
						}
						break;
					}
					break;
				case 4:
				case 8:
					//To avoid to handover frequently
					if ((psROAM->RoamTime != 0) && 
						(( (hal_get_time_count( pHwData )/ 10) - psROAM->RoamTime) > 30) )
					{
						//Too frequent
						#ifdef _PE_STATE_DUMP_
						//WBDEBUG(("Too frequnetly handover.\n"));
						#endif
					}
					else
					{
						psLOCAL->RoamStatus = 1;
						TryToHandover(Adapter);
					}
					break;
				case 20:
					psROAM->wSignalLostNum = 0;
					break;
				default:
					break;
			}
			psROAM->wSignalLostNum++;
		}
		vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
	}
	else
	{
		psROAM->wState = QUERY_ESS;
		psROAM->wUnlockNum++;
		vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
	}
}

void vRoamProc_QueryEssTimeout(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg)
{
	K_MSG	sMsg;
	u16	wReason;
	u8	boDisconnect = FALSE;

	if (boCheckConnect(Adapter) == TRUE)
	{
		psROAM->wUnlockNum = 0;
		if (boCheckSignal(Adapter) == TRUE)
		{
			psROAM->wSignalLostNum = 0;
			psROAM->wState = ACTIVE;
		}
		else
		{
			psROAM->wSignalLostNum++;
			psROAM->wState = DOUBLE_CHK_LOCK;
		}
		vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
	}
	else
	{
		switch (psROAM->wUnlockNum)
		{
			case 2:	//scanning
				{
					SCAN_REQ_PARA	sScanReqPara;

					//TryToHandover(Adapter);
					//prepare to roam to another AP
					sMsg.wMsgType = SMEMSG_SCAN_REQ;
					//Scan with unicast SSID. Only change SSID parameters.
					memcpy( &sScanReqPara, psSCANREQ , sizeof(SCAN_REQ_PARA) );
					memcpy( &sScanReqPara.sSSID, &psSME->sDesiredSSID, sizeof(struct SSID_Element) );
					sMsg.pMsgPtr = &sScanReqPara;
					SME_Entry(Adapter, &sMsg);
					break;
				}
			case 4: //perform roaming
				psLOCAL->RoamStatus = 2;
				TryToHandover(Adapter);
				break;
			case 7:
				boDisconnect = TRUE;
				break;
			default:
				break;
		}
		if (boDisconnect)
		{
			//No candidate to join
			//psROAM->wState = INACTIVE; It will be reset at SME
			vRoamTimerStop(Adapter);

			FillEventLog(Adapter, EVENT_LOST_SIGNAL);

			//info SME module, psLOCAL->wConnectedSTAindex may still not equal to 0
			wReason = DISASS_REASON_LEFT_BSS;
			sMsg.wMsgType = SMEMSG_END_ROAMING;
			sMsg.pMsgPtr = &wReason;
			SME_Entry(Adapter, &sMsg);
		}
		else
		{
			psROAM->wUnlockNum++;
			vRoamTimerStart(Adapter, ROAM_TIME_PERIOD);
		}
	}
}
#endif

void vRoamProc_RcvDeAuthInd(PWB32_ADAPTER Adapter, K_MSG* psRoamMsg)
{
	K_MSG	sMsg;
	u16	wReason;

	//psLOCAL->wConnectedSTAindex had been cleared in SME module
	vRoamTimerStop(Adapter);
	if (*((u16 *)psRoamMsg->pMsgPtr) == REASON_MIC_ERROR)
	{
		//psROAM->wState = ROAM_INACTIVE;  It will be reset at SME
		//info SME module
		wReason = REASON_MIC_ERROR;
		sMsg.wMsgType = SMEMSG_END_ROAMING;
		sMsg.pMsgPtr = &wReason;
		SME_Entry(Adapter, &sMsg);
	}
	else
	{
		//Although receiving this command may be due to the reason that the settings of AP are
		//modified, we still don't rejoin here. Let NDIS take it.(Disconnet and
		//reconnect)
		//psROAM->wState = ROAM_INACTIVE;  It will be reset at SME
		//info SME module
		wReason = REASON_CLASS3_FRAME_FROM_NONASSO_STA;
		sMsg.wMsgType = SMEMSG_END_ROAMING;
		sMsg.pMsgPtr = &wReason;
		SME_Entry(Adapter, &sMsg);
	}
}

//added by ws 02/02/05 for wep key detection
void Wepkey_ErrCheck( PWB32_ADAPTER Adapter)
{
	if (CURRENT_LINK_ON)
	{
		u8 bss_type = ESS_NET;
		sme_get_bss_type((void *)Adapter, &bss_type);

		if (bss_type == ESS_NET)
		{
			if (--Adapter->sLocalPara.WepKeyDetectTimerCount== 0)
			{
		            Adapter->sLocalPara.bWepKeyError= 
					Adapter->sLocalPara.bToSelfPacketReceived
					? FALSE
					: TRUE;
                    hal_set_accept_promiscuous( &Adapter->sHwData,0);
			}
		}
		else
		{
			Adapter->sLocalPara.bWepKeyError= FALSE;
		}
	}
}


